﻿using Newtonsoft.Json;
using SocketMessaging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MyWordAddIn.Tool
{

    /// <summary>
    /// Net : 提供静态方法，对常用的网络操作进行封装
    /// </summary>
    public sealed class Net
    {
        private Net()
        {
        }

        /// <summary>
        /// 向远程主机发送数据
        /// </summary>
        /// <param name="socket">要发送数据且已经连接到远程主机的 Socket</param>
        /// <param name="buffer">待发送的数据</param>
        /// <param name="outTime">发送数据的超时时间，以秒为单位，可以精确到微秒</param>
        /// <returns>0:发送数据成功；-1:超时；-2:发送数据出现错误；-3:发送数据时出现异常</returns>
        /// <remarks >
        /// 当 outTime 指定为-1时，将一直等待直到有数据需要发送
        /// </remarks>
        public static int SendData(TcpClient client, byte[] buffer, int outTime = 100)
        {

            System.Net.Sockets.Socket socket = client.Socket;

            if (socket == null || socket.Connected == false)
            {
                throw new ArgumentException("参数socket 为null，或者未连接到远程计算机");
            }
            if (buffer == null || buffer.Length == 0)
            {
                throw new ArgumentException("参数buffer 为null ,或者长度为 0");
            }

            int flag = 0;
            try
            {
                int left = buffer.Length;
                int sndLen = 0;

                //while (true)
                //{
                    //if ((socket.Poll(outTime * 100, SelectMode.SelectWrite) == true))
                  //  {        // 收集了足够多的传出数据后开始发送
                        
                        client.Send(buffer);
                        //left -= buffer.Length ;
                        //if (left == 0)
                        //{                                        // 数据已经全部发送
                        //    flag = 0;
                        //    break;
                        //}
                        //else
                        //{
                        //    if (sndLen > 0)
                        //    {                                    // 数据部分已经被发送
                        //        continue;
                        //    }
                        //    else
                        //    {                                                // 发送数据发生错误
                        //        flag = -2;
                        //        break;
                        //    }
                        //}
                    //}
                    //else
                    //{                                                        // 超时退出
                    //    flag = -1;
                    //    break;
                    //}
                //}
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                flag = -3;
            }
            return flag;
        }

        public static int SendData(TcpClient client, string buffer, int outTime)
        {

            int flag = 0;

            try
            {
                   // 收集了足够多的传出数据后开始发送
                client.Send(buffer);
              
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);

                flag = -1;
            }
            return flag;
        }

        public static int sendFIleByString(TcpClient client, string text, string fileName, int maxBufferLength, int fd)
        {

            MyFileInfo fileInfo = new MyFileInfo();

            string buffer;

            fileName = fileName + ".docx";

            int flag = 0;

            try
            {
                if (text.Length <= maxBufferLength)
                {
                    // 可一次性发送

                    fileInfo.Name = fileName;

                    fileInfo.content = Encoding.UTF8.GetBytes(text);


                    ReceiveData<MyFileInfo> receiveData = new ReceiveData<MyFileInfo>(

                       "receive_file",
                       1,
                       fileInfo,
                       fd
                    );

                    client.Send(JsonConvert.SerializeObject(receiveData));
                }

                /* 循环读取文件,并发送 */

               int leftLen = text.Length;

               int readLen = 0;


                while (leftLen > 0)
                {
                    if (leftLen < maxBufferLength)
                    {
                        buffer = text.Substring(readLen, leftLen);

                        readLen += leftLen;
                    }
                    else
                    {
                        buffer = text.Substring(readLen, maxBufferLength);
                        readLen += maxBufferLength;
                    }

                    fileInfo = new MyFileInfo();


                    fileInfo.Name = fileName;

                    fileInfo.content = Encoding.UTF8.GetBytes(buffer);

                    ReceiveData<MyFileInfo> receiveData = new ReceiveData<MyFileInfo>(
                       "receive_file",
                       1,
                       fileInfo,
                       fd
                    );

                    client.Send(JsonConvert.SerializeObject(receiveData));
                   
                    leftLen -= readLen;
                }
            }
            catch (IOException e)
            {
                MessageBox.Show(e.Message);
                flag = -4;
            }
            return flag;
        }


        /// <summary>
        /// 向远程主机发送文件
        /// </summary>
        /// <param name="socket" >要发送数据且已经连接到远程主机的 socket</param>
        /// <param name="fileName">待发送的文件名称</param>
        /// <param name="maxBufferLength">文件发送时的缓冲区大小</param>
        /// <param name="outTime">发送缓冲区中的数据的超时时间</param>
        /// <returns>0:发送文件成功；-1:超时；-2:发送文件出现错误；-3:发送文件出现异常；-4:读取待发送文件发生错误</returns>
        /// <remarks >
        /// 当 outTime 指定为-1时，将一直等待直到有数据需要发送
        /// </remarks>
        public static int SendFile(TcpClient client, string fileName, int maxBufferLength, int outTime, int fd)
        {
            if (fileName == null || maxBufferLength <= 0)
            {
                throw new ArgumentException("待发送的文件名称为空或发送缓冲区的大小设置不正确.");
            }
            int flag = 0;
            try
            {
                FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
                long fileLen = fs.Length;                        // 文件长度
                long leftLen = fileLen;                            // 未读取部分
                int readLen = 0;                                // 已读取部分
                byte[] buffer = null;


                MyFileInfo fileInfo = new MyFileInfo();


                if (fileLen <= maxBufferLength)
                {            /* 文件可以一次读取*/
                    buffer = new byte[fileLen];
                    readLen = fs.Read(buffer, 0, (int)fileLen);

                    int point = fileName.LastIndexOf("\\") + 1;

                    fileInfo.Name = fileName.Substring(point, fileName.Length - point);

                    fileInfo.content = buffer;

                    ReceiveData<MyFileInfo> receiveData = new ReceiveData<MyFileInfo>(

                       "receive_file",
                       1,
                       fileInfo,
                       fd
                    );

                    flag = SendData(client, JsonConvert.SerializeObject(receiveData), outTime);
                }
                else
                {
                    /* 循环读取文件,并发送 */

                    while (leftLen != 0)
                    {
                        if (leftLen < maxBufferLength)
                        {
                            buffer = new byte[leftLen];
                            readLen = fs.Read(buffer, 0, Convert.ToInt32(leftLen));
                        }
                        else
                        {
                            buffer = new byte[maxBufferLength];
                            readLen = fs.Read(buffer, 0, maxBufferLength);
                        }

                        int point = fileName.LastIndexOf("\\") + 1;

                        fileInfo.Name = fileName.Substring(point, fileName.Length - point);

                        fileInfo.content = buffer;

                        ReceiveData<MyFileInfo> receiveData = new ReceiveData<MyFileInfo>(
                           "receive_file",
                           1,
                           fileInfo,
                           fd
                        );

                        if ((flag = SendData(client, JsonConvert.SerializeObject(receiveData), outTime)) < 0)
                        {
                            break;
                        }
                        leftLen -= readLen;
                    }
                }
                fs.Flush();
                fs.Close();
            }
            catch (IOException e)
            {
                MessageBox.Show(e.Message);
                flag = -4;
            }
            return flag;
        }

    }
}
